package com.csw.mllib

import org.apache.spark.ml.classification.{LogisticRegression, LogisticRegressionModel}
import org.apache.spark.sql.{DataFrame, Dataset, Row, SparkSession}

object Demo02Persion {
  def main(args: Array[String]): Unit = {

    val spark: SparkSession = SparkSession
      .builder()
      .master("local")
      .appName("persion")
      .config("spark.sql.shuffle.partitions", 2)
      .getOrCreate()

    //导入隐式转换
    import spark.implicits._

    //导入所有spark.sql方法
    import org.apache.spark.sql.functions._

    /**
      *
      * 1、特征工程
      * 将原始数据转换成公式可以识别的数据
      *
      * 这里的是已经被做完特种工程的数据了
      *
      */

    //通过spark  sql读取svm格式的数据

    val persionDF: DataFrame = spark
      .read
      .format("libsvm")
      .load("spark/data/人体指标.txt")

    persionDF.show(false)


    /**
      * 2、切分训练集和测试集
      * 训练集--->训练模型
      * 测试集--->测试模型准确率
      *
      * 一般训练集0.7  测试集0.3
      *
      */

    val splitDF: Array[Dataset[Row]] = persionDF.randomSplit(Array(0.7, 0.3))

    //训练集
    val trainDF: Dataset[Row] = splitDF(0)
    //测试集
    val testDF: Dataset[Row] = splitDF(1)


    /**
      * 3、选择算法
      *
      * 结果是离散值--> 分类
      *
      * 逻辑回归
      *
      */

    //构建算法执行参数
    val logisticRegression: LogisticRegression = new LogisticRegression()
      .setMaxIter(10)//最大迭代次数
      .setFitIntercept(true)//是否有截距


    /**
      *
      * 4、训练模型
      * 将训练集带人算法训练模型 ---  确定k和b
      *
      * 模型包含公式和参数
      *
      */
    val model: LogisticRegressionModel = logisticRegression.fit(trainDF)

    /**
      * 5、模型评估
      * 使用模型预测测试集的数据，判断和原始标记是否一致，计算准确率
      *
      */
    val frame: DataFrame = model.transform(testDF)

    /**
      *
      * 计算准确率
      *
      */
    val result: DataFrame = frame.select(sum(when($"label"=== $"prediction",1).otherwise(0)))

    result.show()


    /**
      * 如果准确率还可以就保存模型
      * 保存到hdfs中
      *
      */
    model.save("spark/data/mode1")
  }
}
